﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using DATLib;
using DimsMapper.Modules;

namespace DimsMapper
{
    static class DatFiles
    {
        /// <summary>
        /// Получает список всех имеющихся файлов с заданным расширением в указанном подкаталоге игры
        /// проход будет осуществелне по всем подключенным dat
        /// </summary>
        /// <param name="folder"></param>
        /// <param name="extFile"></param>
        /// <returns></returns>
        public static List<string> FindAllFilesByExt(string folder, string extFile)
        {
            List<string> fileData = new List<string>();

            for (int i = Main.DataBases().Count - 1; i >= 0; i--)
            {
                var item = Main.DataBases()[i];
                if (item.IsDat) {
                    fileData.AddRange(DATManage.GetFileList(item.DataBasePath, folder, extFile));
                } else {
                    string fullPath = Path.Combine(item.DataBasePath, folder);
                    if (Directory.Exists(fullPath)) {
                        string[] list = Directory.GetFiles(fullPath, "*" + extFile);
                        int pos = fullPath.Length;
                        for (int n = 0; n < list.Length; n++)
                        {
                            list[n] = list[n].Substring(pos);
                        }
                        fileData.AddRange(list);
                    }
                }
            }
            return new HashSet<string>(fileData, StringComparer.OrdinalIgnoreCase).ToList(); // убрать дубликаты из списка
        }

        /// <summary>
        /// Получает поток к открываемому файлу (еcли файл находится в DAT то будет создан буфер для быстрого последующего доступа к нему) 
        /// </summary>
        /// <param name="pathFile"></param>
        /// <returns></returns>
        public static DBFile OpenFileBuffered(string pathFile)
        {
            // Начинаем снизу вверх (открываем первый попавшийся файл в цепочке путей)
            for (int i = Main.DataBases().Count - 1; i >= 0; i--)
            {
                var item = Main.DataBases()[i];
                if (item.IsDat) {
                    BinaryReader file = DATManage.GetFileStreamData(pathFile, item.DataBasePath);
                    if (file != null) return new DBFile(null, file);
                } else {
                    // открываем файл вне dat
                    string fullPath = Path.Combine(item.DataBasePath, pathFile); // добавить путь к запрашиваемому файлу
                    if (File.Exists(fullPath)) {
                        BinaryReader file = new BinaryReader(File.Open(fullPath, FileMode.Open, FileAccess.Read, FileShare.ReadWrite));
                        return new DBFile(fullPath, file);
                    }
                }
            }
            return null;
        }

        public static DBFile OpenFile(string pathFile)
        {
            // Начинаем снизу вверх (открываем первый попавшийся файл в цепочке путей)
            for (int i = Main.DataBases().Count - 1; i >= 0; i--)
            {
                var item = Main.DataBases()[i];
                if (item.IsDat) {
                    BinaryReader file = DATManage.GetFileStreamTempData(pathFile, item.DataBasePath);
                    if (file != null) return new DBFile(null, file);
                } else {
                    // открываем файл вне dat
                    string fullPath = Path.Combine(item.DataBasePath, pathFile); // добавить путь к запрашиваемому файлу
                    if (File.Exists(fullPath)) {
                        BinaryReader file = new BinaryReader(File.Open(fullPath, FileMode.Open, FileAccess.Read, FileShare.ReadWrite));
                        return new DBFile(fullPath, file);
                    }
                }
            }
            return null;
        }

        /// <summary>
        /// Читает текстовй файл
        /// </summary>
        /// <param name="pathFile"></param>
        /// <returns></returns>
        public static List<string> ReadFile(string pathFile, Encoding encoding)
        {
            // Начинаем снизу вверх (открываем первый попавшийся файл в цепочке путей)
            for (int i = Main.DataBases().Count - 1; i >= 0; i--)
            {
                var item = Main.DataBases()[i];
                if (item.IsDat) {
                    byte[] file = DATManage.GetFileTempData(pathFile, item.DataBasePath);
                    // бинарные данные преобразовать в строковый массив
                    if (file != null) {
                        List<string> contentFile = new List<string>();
                        int position = 0;
                        bool inComment = false;
                        for (int len = 0; len < file.Length; len++)
                        {
                            if (inComment) {
                                while (file[len] != '\n') { if (++len >= file.Length) return contentFile; } // пропускаем коментарий до новой строки
                                position = len + 1;
                                inComment = false;
                            } else {
                                if (file[len] == '\n' || file[len] == ';' || file[len] == '#') {
                                    contentFile.Add(encoding.GetString(file, position, len - position).Trim());

                                    if (file[len] == ';' || file[len] == '#') inComment = true;
                                    position = len + 1;
                                }
                            }
                        }
                        return contentFile;
                    }
                } else {
                    // открываем файл вне dat
                    string fullPath = Path.Combine(item.DataBasePath, pathFile); // добавить путь к запрашиваемому файлу
                    if (File.Exists(fullPath)) {
                        string[] content = File.ReadAllLines(fullPath, encoding);
                        char[] comment = new char[] { ';', '#' };
                        for (int n = 0; n < content.Length; n++)
                        {
                            int m = content[n].IndexOfAny(comment);
                            if (m != -1) {
                                content[n] = content[n].Remove(m).Trim();
                            } else {
                                content[n] = content[n].Trim();
                            }
                        }
                        return content.ToList();
                    }
                }
            }
            return null;
        }

        public static DBFile OpenMapperFile(string pathFile)
        {
            string fullPath = Path.Combine(Application.StartupPath, pathFile); // добавить путь к запрашиваемому файлу
            if (File.Exists(fullPath)) {
                BinaryReader file = new BinaryReader(File.Open(fullPath, FileMode.Open, FileAccess.Read, FileShare.Read));
                return new DBFile(fullPath, file);
            }
            return null;
        }
    }
}
